package com.lingjtx.common.core.util;

import com.lingjtx.common.core.constant.Const;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Map;
import java.util.TreeMap;

/**
 * 公共的工具类
 *
 * @author John Liu
 */
public class CommonUtil {

    /**
     * 随机生成范围在 [startNum, endNum] 的随机数
     *
     * @param startNum
     * @param endNum
     * @return
     */
    public static int randomScope(int startNum, int endNum) {
        return (int) Math.floor(Math.random() * (endNum - startNum) + startNum);
    }

    /**
     * BasicAuth Basic权限认证Base64加密
     *
     * @param username
     * @param password
     * @return 解密后的值
     */
    public static String getBasicAuth(String username, String password) {
        String str = username + ":" + password;
        return Base64.getUrlEncoder().encodeToString(str.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * Get 请求时，按照POP规则把特殊符号替换
     */
    public static String specialUrlEncode(String value) {
        return URLEncoder.encode(value, StandardCharsets.UTF_8)
                .replace("+", "%20")
                .replace("*", "%2A")
                .replace("%7E", "~");
    }

    /**
     * 阿里第三方服务加签
     */
    public static String sign(String stringToSign, String secret, String signMethod) throws Exception {
        SecretKeySpec signingKey = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), signMethod);
        Mac mac = Mac.getInstance(signMethod);
        mac.init(signingKey);
        byte[] rawHmac = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(rawHmac);
    }

    /**
     * 把Map 键值对按照Key的字母排序顺序[ Key=value&Key=value&... ]拼接
     * 阿里验签方法
     */
    public static String stringToSign(Map<String, Object> map) throws Exception {
        StringBuilder sortString = new StringBuilder();
        for (String key : CommonUtil.sortMap(map).keySet()) {
            sortString.append("&")
                    .append(CommonUtil.specialUrlEncode(key))
                    .append("=")
                    .append(CommonUtil.specialUrlEncode(map.get(key).toString()));
        }
        String sign = "GET" +
                "&" +
                CommonUtil.specialUrlEncode("/") +
                "&" +
                CommonUtil.specialUrlEncode(sortString.substring(1));
        return CommonUtil.sign(sign, Const.ALIYUN_ACCESS_SECRET + "&", "HmacSHA1");
    }

    public static Map<String, Object> sortMap(Map<String, Object> map) {
        return new TreeMap<>(map);
    }

    public static String loadPrivateKey(String content) {
        return content != null ? content.replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "") : null;
    }

    public static String loadPrivateKeyByPath(String path) {
        return loadPrivateKey(FileUtil.read(path));
    }
}
